package com.gzhryc.shared_device.common.payment.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayAdvanceOrderState;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayAdvanceServerState;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayNormalPayState;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.Collection;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayConfirmNotify;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayFinishNotify;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayQueryResponse;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalOrderResponse;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalPayNotify;
import com.gzhryc.shared_device.base.enums.EPayState;
import com.gzhryc.shared_device.common.payment.dao.WXPayOrderDao;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.services.dto.WXPayOrderSearch;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

public class WXPayOrderService {

    static Logger log = Logger.getLogger(WXPayOrderService.class);

    public static WXPayOrderService self(Date date) {
        return MultiDBTools.getService(WXPayOrderService.class, date);
    }

    public static WXPayOrderService self(String jdbcKey,Date date) {
        return MultiDBTools.getService(jdbcKey, WXPayOrderService.class, date);
    }

    WXPayOrderDao dao;

    public WXPayOrderService(String jdbcKey,Date date) {
        dao = new WXPayOrderDao(jdbcKey,date);
    }

    public List<WXPayOrder> findBySearch(WXPayOrderSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        conditions.desc("createDate");

        try {
            return dao.findByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public List<WXPayOrder> findByBusinessTradeNo(String businessTradeNo){
        if(StringTools.isNotBlank(businessTradeNo)){
            Conditions conditions = new Conditions(WXPayOrder.class);
            conditions.and().is("businessTradeNo",businessTradeNo);

            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public Long countBySearch(WXPayOrderSearch search){
        Conditions conditions = dao.buildConditions(search);
        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public WXPayOrder getByTradeNo(String tradeNo){
        try {
            return dao.getById(tradeNo);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }
    
    public WXPayOrder getLastByBusinessTradeNo(String businessTradeNo) {
    	if(StringTools.isNotBlank(businessTradeNo)) {
    		Conditions condition = new Conditions(WXPayOrder.class);
    		condition.and().is("businessTradeNo", businessTradeNo);
	        try {
	            return dao.get(condition);
	        } catch (SQLException e) {
	            log.error(e.getMessage(),e);
	        }
    	}
        return null;
    }
    
    public WXPayOrder getByExternalTradeNo(String externalTradeNo){
    	if(StringTools.isNotBlank(externalTradeNo)) {
    		Conditions condition = new Conditions(WXPayOrder.class);
    		condition.and().is("externalTradeNo", externalTradeNo);
	        try {
	            return dao.get(condition);
	        } catch (SQLException e) {
	            log.error(e.getMessage(),e);
	        }
    	}
        return null;
    }
    
    /**
     * 用于商品订单微信支付保存
     * @param payOrder
     * @return
     */
    public boolean add(WXPayOrder payOrder) {
    	try {
			return dao.insert(payOrder) > 0;
		} catch (SQLException e) {
			log.error(e.getMessage(), e);
		}
    	return false;
    }
    
    public boolean closeWaitPay(WXPayOrder payOrder) {
    	return false;
    }
    
    public int payResult(WXPayOrder payOrder, WXPayNormalPayNotify notify) throws LogicException {
        // 检查金额
        if (!payOrder.getPayMoney().equals(notify.getAmount().getPayer_total())) {
            // throw new LogicException("支付金额不正确");
            log.error("微信支付金额不正确，回调信息：" + JsonTools.toJson(notify));
        }
        try {
            payOrder.setExternalTradeNo(notify.getTransaction_id());
            payOrder.setExternalContent(JsonTools.toJson(notify));
            payOrder.setReceiptMoney(notify.getAmount().getPayer_total());
            payOrder.setPayDate(new Date());
            if (EWXPayNormalPayState.SUCCESS.name().equals(notify.getTrade_state())) {
                payOrder.setPayStatus(EPayState.Success.index());
            } else {
                payOrder.setPayStatus(EPayState.Fail.index());
            }
            if(dao.insert(payOrder) > 0){
                if(EPayState.Success.index().equals(payOrder.getPayStatus())){
                    return 1;
                }else {
                    return 0;
                }
            }
        } catch (SQLException e) {
            log.error("微信支付订单处理错误，" + e.getMessage(), e);
        }
        return -1;
    }
    
    /**
     * 用户免押支付
     * @param payOrder
     * @param notify
     * @return
     * @throws LogicException
     */
    public int payResult(WXPayOrder payOrder, WXPayAdvancePayFinishNotify notify) throws LogicException {
        try {
        	String externalPayTradeNo = null;
			if(notify.getCollection() != null) {
				if (notify.getCollection().getDetails() != null && notify.getCollection().getDetails().size() > 0) {
					Collection.CollectionDetails details = notify.getCollection().getDetails().get(0);
					externalPayTradeNo = details.getTransaction_id();
				}
			}
        	
			WXPayOrder updateEntity = new WXPayOrder();
			updateEntity.setTradeNo(payOrder.getTradeNo());
			updateEntity.setExternalPayTradeNo(externalPayTradeNo);
			updateEntity.setExternalPayContent(JsonTools.toJson(notify));
			updateEntity.setPayMoney(notify.getTotal_amount());
			updateEntity.setPayDate(new Date());
			updateEntity.setPayStatus(EPayState.Fail.index());
            if (EWXPayAdvanceServerState.DONE.name().equals(notify.getState())){
            	updateEntity.setPayStatus(EPayState.Success.index());
			}

            if(dao.updateNotNull(updateEntity) > 0){
            	payOrder.setExternalPayTradeNo(externalPayTradeNo);
            	payOrder.setExternalPayContent(updateEntity.getExternalPayContent());
            	payOrder.setPayMoney(updateEntity.getPayMoney());
            	payOrder.setPayDate(updateEntity.getPayDate());
            	payOrder.setPayStatus(updateEntity.getPayStatus());
                if(EPayState.Success.index().equals(payOrder.getPayStatus())){
                    return 1;
                }else {
                    return 0;
                }
            }
        } catch (SQLException e) {
            log.error("微信免押订单处理错误，" + e.getMessage(), e);
        }
        return -1;
    }
    
    public int payResult(WXPayOrder payOrder, WXPayAdvancePayConfirmNotify notify) throws LogicException {
        try {
            payOrder.setExternalTradeNo(notify.getOrder_id());
            payOrder.setExternalContent(JsonTools.toJson(notify));
            payOrder.setPayDate(new Date());
            payOrder.setPayStatus(EPayState.Close.index());
            if (EWXPayAdvanceServerState.DOING.name().equals(notify.getState())) {
				if(EWXPayAdvanceOrderState.USER_CONFIRM.name().equals(notify.getState_description())){
					payOrder.setPayStatus(EPayState.Confirm.index());
				}
			}
            if(dao.insert(payOrder) > 0){
                if(EPayState.Confirm.index().equals(payOrder.getPayStatus())){
                    return 1;
                }else {
                    return 0;
                }
            }
        } catch (SQLException e) {
            log.error("微信免押订单处理错误，" + e.getMessage(), e);
        }
        return -1;
    }

    public boolean updateExternalContent(String tradeNo, String externalContent, Date payDate){
        if(StringTools.isNotBlank(tradeNo) && StringTools.isNotBlank(externalContent)){
            WXPayOrder payOrder = new WXPayOrder();
            payOrder.setTradeNo(tradeNo);
            payOrder.setExternalContent(externalContent);
            payOrder.setPayDate(payDate);

            try {
                return dao.updateNotNull(payOrder) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public WXPayOrder synExternalPayOrder(WXPayOrder payOrder,WXPayNormalOrderResponse externalPayOrder)throws LogicException{
    	if(EWXPayNormalPayState.SUCCESS.name().equals(externalPayOrder.getTrade_state())) {
    		//支付成功
    		if(!EPayState.Success.index().equals(payOrder.getPayStatus())) {
    			WXPayOrder updateEntity = new WXPayOrder();
				updateEntity.setTradeNo(payOrder.getTradeNo());
				updateEntity.setPayMoney(externalPayOrder.getAmount().getTotal());
				updateEntity.setReceiptMoney(externalPayOrder.getAmount().getTotal());
				updateEntity.setPayStatus(EPayState.Success.index());
				try {
					if(dao.updateNotNull(updateEntity) > 0) {
						payOrder.setPayMoney(updateEntity.getPayMoney());
						payOrder.setReceiptMoney(updateEntity.getReceiptMoney());
						payOrder.setPayStatus(updateEntity.getPayStatus());
					}
				} catch (SQLException e) {
					log.error(e.getMessage(), e);
					throw new LogicException("修改微信支付订单状态失败");
				}
    		}
    	}else if(EWXPayNormalPayState.REVOKED.name().equals(externalPayOrder.getTrade_state())) {
    		//已撤销
    		if(!EPayState.Cancel.index().equals(payOrder.getPayStatus())) {
    			WXPayOrder updateEntity = new WXPayOrder();
				updateEntity.setTradeNo(payOrder.getTradeNo());
				updateEntity.setPayMoney(0);
				updateEntity.setReceiptMoney(0);
				updateEntity.setPayStatus(EPayState.Cancel.index());
				try {
					if(dao.updateNotNull(updateEntity) > 0) {
						payOrder.setPayMoney(updateEntity.getPayMoney());
						payOrder.setReceiptMoney(updateEntity.getReceiptMoney());
						payOrder.setPayStatus(updateEntity.getPayStatus());
					}
				} catch (SQLException e) {
					log.error(e.getMessage(), e);
					throw new LogicException("修改微信支付订单状态失败");
				}
    		}
    	}
        return payOrder;
    }
    
    public WXPayOrder synExternalPayOrder(WXPayOrder payOrder,WXPayAdvancePayQueryResponse externalPayOrder)throws LogicException{
    	if(EWXPayAdvanceServerState.DOING.name().equals(externalPayOrder.getState())) {
    		if(EWXPayAdvanceOrderState.USER_CONFIRM.name().equals(externalPayOrder.getState_description())){
    			if(!EPayState.Confirm.index().equals(payOrder.getPayStatus())) {
    				WXPayOrder updateEntity = new WXPayOrder();
    				updateEntity.setTradeNo(payOrder.getTradeNo());
    				updateEntity.setPayStatus(EPayState.Confirm.index());
    				try {
						if(dao.updateNotNull(updateEntity) > 0) {
							payOrder.setPayStatus(updateEntity.getPayStatus());
						}
					} catch (SQLException e) {
						log.error(e.getMessage(), e);
						throw new LogicException("修改微信支付订单状态失败");
					}
        		}
			}else if(EWXPayAdvanceOrderState.MCH_COMPLETE.name().equals(externalPayOrder.getState_description())){
				boolean toUpdate = false;
	    		if(!externalPayOrder.getTotal_amount().equals(payOrder.getPayMoney()) || payOrder.getReceiptMoney() != 0) {
	    			toUpdate = true;
	    		}
				
				if(!EPayState.FinishToWaitPay.index().equals(payOrder.getPayStatus()) || toUpdate) {
    				WXPayOrder updateEntity = new WXPayOrder();
    				updateEntity.setTradeNo(payOrder.getTradeNo());
    				updateEntity.setPayMoney(externalPayOrder.getTotal_amount());
    				updateEntity.setReceiptMoney(0);
    				updateEntity.setPayStatus(EPayState.FinishToWaitPay.index());
    				try {
						if(dao.updateNotNull(updateEntity) > 0) {
							payOrder.setPayMoney(updateEntity.getPayMoney());
							payOrder.setPayStatus(updateEntity.getPayStatus());
						}
					} catch (SQLException e) {
						log.error(e.getMessage(), e);
						throw new LogicException("修改微信支付订单状态失败");
					}
        		}
			}
    		
    	}else if(EWXPayAdvanceServerState.DONE.name().equals(externalPayOrder.getState())) {
    		boolean toUpdate = false;
    		if(!externalPayOrder.getTotal_amount().equals(payOrder.getPayMoney()) ||
    				!externalPayOrder.getTotal_amount().equals(payOrder.getReceiptMoney())) {
    			toUpdate = true;
    		}
    		
    		if(!EPayState.Success.index().equals(payOrder.getPayStatus()) || toUpdate) {
    			WXPayOrder updateEntity = new WXPayOrder();
				updateEntity.setTradeNo(payOrder.getTradeNo());
				updateEntity.setPayMoney(externalPayOrder.getTotal_amount());
				updateEntity.setReceiptMoney(externalPayOrder.getTotal_amount());
				updateEntity.setPayStatus(EPayState.Success.index());
				try {
					if(dao.updateNotNull(updateEntity) > 0) {
						payOrder.setPayMoney(updateEntity.getPayMoney());
						payOrder.setPayStatus(updateEntity.getPayStatus());
					}
				} catch (SQLException e) {
					log.error(e.getMessage(), e);
					throw new LogicException("修改微信支付订单状态失败");
				}
    		}
    	}else if(EWXPayAdvanceServerState.REVOKED.name().equals(externalPayOrder.getState())) {
    		boolean toUpdate = false;
    		if(payOrder.getPayMoney() != 0 || payOrder.getReceiptMoney() != 0) {
    			toUpdate = true;
    		}
    		
    		if(!EPayState.Cancel.index().equals(payOrder.getPayStatus()) || toUpdate) {
    			WXPayOrder updateEntity = new WXPayOrder();
				updateEntity.setTradeNo(payOrder.getTradeNo());
				updateEntity.setPayMoney(0);
				updateEntity.setReceiptMoney(0);
				updateEntity.setPayStatus(EPayState.Cancel.index());
				try {
					if(dao.updateNotNull(updateEntity) > 0) {
						payOrder.setPayStatus(updateEntity.getPayStatus());
					}
				} catch (SQLException e) {
					log.error(e.getMessage(), e);
					throw new LogicException("修改微信支付订单状态失败");
				}
    		}
    	}else if(EWXPayAdvanceServerState.EXPIRED.name().equals(externalPayOrder.getState())) {
    		boolean toUpdate = false;
    		if(payOrder.getPayMoney() != 0 || payOrder.getReceiptMoney() != 0) {
    			toUpdate = true;
    		}
    		
    		if(!EPayState.Close.index().equals(payOrder.getPayStatus()) || toUpdate) {
    			WXPayOrder updateEntity = new WXPayOrder();
				updateEntity.setTradeNo(payOrder.getTradeNo());
				updateEntity.setPayMoney(0);
				updateEntity.setReceiptMoney(0);
				updateEntity.setPayStatus(EPayState.Close.index());
				try {
					if(dao.updateNotNull(updateEntity) > 0) {
						payOrder.setPayStatus(updateEntity.getPayStatus());
					}
				} catch (SQLException e) {
					log.error(e.getMessage(), e);
					throw new LogicException("修改微信支付订单状态失败");
				}
    		}
    	}else {
    		throw new LogicException("无法同步的微信预支付订单");
    	}
    	return payOrder;
    }
}
